﻿#region - 版 本 注 释 -
/*----------------------------------------------------------------
 * 版权所有 (c) 2024   保留所有权利。
 * CLR版本：4.0.30319.42000
 * 机器名称：DESKTOP-GLJ2Q8J
 * 公司名称：
 * 命名空间：AutoCAD.EntityTool
 * 唯一标识：b893f674-d9d1-4fd6-88a5-6b43f5b1d8e0
 * 文件名：BlockTools
 * 当前用户域：DESKTOP-GLJ2Q8J
 * 
 * 创建者：Guo-79991
 * 电子邮箱：799919859@qq.com
 * 创建时间：2024/7/15 12:05:36
 * 版本：V1.0.0
 *
 * 功能描述(Description):
 * 参考文档(Reference):
 * 数据表(Tables):
 * 作者(Author):Guo
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/
#endregion - 版 本 注 释 -

namespace AutoCAD.EntityTools.Jig
{
    public class RectangleJig : EntityJig
    {
        private Point3d _firstCorner;
        private Point3d _oppositeCorner;
        private string _prompt;
        private string[] _keywords;
        private bool _isDynamicMode;

        /// <summary>
        /// 矩形Jig构造函数
        /// </summary>
        public RectangleJig(Point3d firstCorner, string prompt, string[] keywords = null)
            : base(new Polyline())
        {
            _firstCorner = firstCorner;
            _oppositeCorner = firstCorner;
            _prompt = prompt;
            _keywords = keywords;
            _isDynamicMode = true;

            InitializeRectangle();
        }

        /// <summary>
        /// 初始化矩形多段线
        /// </summary>
        private void InitializeRectangle()
        {
            var polyline = (Polyline)Entity;
            polyline.SetDatabaseDefaults();

            // 创建4个顶点（初始为同一个点）
            for (int i = 0; i < 4; i++)
            {
                polyline.AddVertexAt(i, new Point2d(_firstCorner.X, _firstCorner.Y), 0, 0, 0);
            }

            polyline.Closed = true;
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            var jigOptions = new JigPromptPointOptions(_prompt)
            {
                UserInputControls = UserInputControls.Accept3dCoordinates |
                                   UserInputControls.NoNegativeResponseAccepted,
                AppendKeywordsToMessage = false,
                BasePoint = _firstCorner,
                UseBasePoint = true,
                Cursor = Autodesk.AutoCAD.EditorInput.CursorType.RubberBand
            };

            // 添加关键字
            if (_keywords != null && _keywords.Length > 0)
            {
                foreach (var keyword in _keywords)
                {
                    jigOptions.Keywords.Add(keyword);
                }
            }

            // 添加空格作为确认关键字
            jigOptions.Keywords.Add(" ");
            jigOptions.Keywords.Add("Cancel");

            var promptResult = prompts.AcquirePoint(jigOptions);

            if (promptResult.Status == PromptStatus.Cancel ||
                promptResult.Status == PromptStatus.Error)
                return SamplerStatus.Cancel;

            if (promptResult.Status == PromptStatus.Keyword)
            {
                return SamplerStatus.OK;
            }

            // 检查点是否有效
            if (promptResult.Value.DistanceTo(_oppositeCorner) < Tolerance.Global.EqualPoint)
                return SamplerStatus.NoChange;

            _oppositeCorner = promptResult.Value;

            return SamplerStatus.OK;
        }

        protected override bool Update()
        {
            try
            {
                var polyline = (Polyline)Entity;

                // 计算矩形的四个角点
                Point3d bottomLeft = new Point3d(
                    Math.Min(_firstCorner.X, _oppositeCorner.X),
                    Math.Min(_firstCorner.Y, _oppositeCorner.Y),
                    0);

                Point3d topRight = new Point3d(
                    Math.Max(_firstCorner.X, _oppositeCorner.X),
                    Math.Max(_firstCorner.Y, _oppositeCorner.Y),
                    0);

                // 更新多段线顶点
                polyline.SetPointAt(0, new Point2d(bottomLeft.X, bottomLeft.Y));
                polyline.SetPointAt(1, new Point2d(topRight.X, bottomLeft.Y));
                polyline.SetPointAt(2, new Point2d(topRight.X, topRight.Y));
                polyline.SetPointAt(3, new Point2d(bottomLeft.X, topRight.Y));

                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Update failed: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 获取创建的矩形多段线
        /// </summary>
        public Polyline GetRectangle() => (Polyline)Entity;

        /// <summary>
        /// 获取矩形宽度
        /// </summary>
        public double GetWidth()
        {
            return Math.Abs(_oppositeCorner.X - _firstCorner.X);
        }

        /// <summary>
        /// 获取矩形高度
        /// </summary>
        public double GetHeight()
        {
            return Math.Abs(_oppositeCorner.Y - _firstCorner.Y);
        }

        /// <summary>
        /// 获取矩形面积
        /// </summary>
        public double GetArea()
        {
            return GetWidth() * GetHeight();
        }

        /// <summary>
        /// 设置动态模式
        /// </summary>
        public void SetDynamicMode(bool isDynamic) => _isDynamicMode = isDynamic;
    }

    public static class RectangleCreationExtensions
    {
        private const double MinimumSize = 0.1;

        /// <summary>
        /// 创建矩形（自动添加到模型空间）
        /// </summary>
        public static ObjectId CreateRectangle(this Document document, short colorIndex = 1)
        {
            return CreateRectangleInternal(document, null, null, colorIndex);
        }

        /// <summary>
        /// 创建矩形（指定事务和块表记录）
        /// </summary>
        public static ObjectId CreateRectangle(this Document document, Transaction transaction,
            BlockTableRecord blockTableRecord, short colorIndex = 1, string message = "指定第一个角点")
        {
            if (transaction == null) throw new ArgumentNullException(nameof(transaction));
            if (blockTableRecord == null) throw new ArgumentNullException(nameof(blockTableRecord));

            return CreateRectangleInternal(document, transaction, blockTableRecord, colorIndex, message);
        }

        private static ObjectId CreateRectangleInternal(Document document,
            Transaction transaction, BlockTableRecord blockTableRecord,
            short colorIndex, string message = "指定第一个角点")
        {
            var editor = document.Editor;
            var database = document.Database;

            try
            {
                // 获取第一个角点
                var firstCornerResult = editor.GetPoint(message);
                if (firstCornerResult.Status != PromptStatus.OK)
                    return ObjectId.Null;

                var firstCorner = firstCornerResult.Value;

                // 创建并运行Jig
                var rectangleJig = new RectangleJig(firstCorner, "\n指定另一个角点或 [尺寸(D)/取消(Cancel)]:",
                    new[] { "D", "Cancel" });

                var dragResult = editor.Drag(rectangleJig);

                Polyline rectangle = null;

                switch (dragResult.Status)
                {
                    case PromptStatus.OK:
                        rectangle = rectangleJig.GetRectangle();
                        break;

                    case PromptStatus.Keyword:
                        switch (dragResult.StringResult)
                        {
                            case "D":
                                rectangle = CreateRectangleByDimensions(editor, firstCorner);
                                break;
                            case "Cancel":
                                return ObjectId.Null;
                            case " ":
                                return ObjectId.Null;
                        }
                        break;

                    case PromptStatus.Cancel:
                        return ObjectId.Null;

                    default:
                        return ObjectId.Null;
                }

                if (rectangle == null || !IsValidRectangle(rectangle))
                {
                    editor.WriteMessage("\n创建失败: 无效的矩形尺寸");
                    return ObjectId.Null;
                }

                rectangle.ColorIndex = colorIndex;
                rectangle.ConstantWidth = 0; // 设置线宽为0

                ObjectId rectangleId;
                if (transaction != null && blockTableRecord != null)
                {
                    rectangleId = rectangle.AddToDatabase(transaction, blockTableRecord);
                }
                else
                {
                    rectangleId = database.AddEntityToModelSpace(rectangle);
                }

                double width = Math.Abs(rectangle.GetPoint2dAt(1).X - rectangle.GetPoint2dAt(0).X);
                double height = Math.Abs(rectangle.GetPoint2dAt(2).Y - rectangle.GetPoint2dAt(1).Y);

                editor.WriteMessage($"\n创建成功! 宽度: {width:F2}, 高度: {height:F2}, 面积: {width * height:F2}");
                return rectangleId;
            }
            catch (Exception ex)
            {
                editor.WriteMessage($"\n创建矩形时发生错误: {ex.Message}");
                return ObjectId.Null;
            }
        }

        /// <summary>
        /// 通过尺寸方式创建矩形
        /// </summary>
        private static Polyline CreateRectangleByDimensions(Editor editor, Point3d firstCorner)
        {
            try
            {
                // 获取宽度
                var widthOptions = new PromptDistanceOptions("\n指定宽度:")
                {
                    DefaultValue = 10.0,
                    UseBasePoint = true,
                    BasePoint = firstCorner,
                    UseDashedLine = true
                };

                var widthResult = editor.GetDistance(widthOptions);
                if (widthResult.Status != PromptStatus.OK)
                    return null;

                double width = widthResult.Value;
                if (width < MinimumSize)
                {
                    editor.WriteMessage($"\n警告: 宽度太小，已设置为最小值 {MinimumSize}");
                    width = MinimumSize;
                }

                // 获取高度
                var heightOptions = new PromptDistanceOptions("\n指定高度:")
                {
                    DefaultValue = 10.0,
                    UseBasePoint = true,
                    BasePoint = firstCorner,
                    UseDashedLine = true
                };

                var heightResult = editor.GetDistance(heightOptions);
                if (heightResult.Status != PromptStatus.OK)
                    return null;

                double height = heightResult.Value;
                if (height < MinimumSize)
                {
                    editor.WriteMessage($"\n警告: 高度太小，已设置为最小值 {MinimumSize}");
                    height = MinimumSize;
                }

                // 确认矩形方向
                var directionOptions = new PromptKeywordOptions("\n选择矩形方向 [右上(UR)/右下(DR)/左上(UL)/左下(DL)]:")
                {
                    AllowNone = true,
                    AppendKeywordsToMessage = true
                };
                directionOptions.Keywords.Add("UR");
                directionOptions.Keywords.Add("DR");
                directionOptions.Keywords.Add("UL");
                directionOptions.Keywords.Add("DL");
                directionOptions.Keywords.Default = "UR";

                var directionResult = editor.GetKeywords(directionOptions);
                if (directionResult.Status != PromptStatus.OK)
                    return null;

                // 计算另一个角点
                Point3d oppositeCorner = firstCorner;
                switch (directionResult.StringResult)
                {
                    case "UR": // 右上
                        oppositeCorner = new Point3d(firstCorner.X + width, firstCorner.Y + height, firstCorner.Z);
                        break;
                    case "DR": // 右下
                        oppositeCorner = new Point3d(firstCorner.X + width, firstCorner.Y - height, firstCorner.Z);
                        break;
                    case "UL": // 左上
                        oppositeCorner = new Point3d(firstCorner.X - width, firstCorner.Y + height, firstCorner.Z);
                        break;
                    case "DL": // 左下
                        oppositeCorner = new Point3d(firstCorner.X - width, firstCorner.Y - height, firstCorner.Z);
                        break;
                }

                // 创建矩形多段线
                return CreateRectangleFromCorners(firstCorner, oppositeCorner);
            }
            catch (Exception ex)
            {
                editor.WriteMessage($"\n尺寸方式创建矩形时发生错误: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 根据两个角点创建矩形多段线
        /// </summary>
        private static Polyline CreateRectangleFromCorners(Point3d corner1, Point3d corner2)
        {
            var polyline = new Polyline();
            polyline.SetDatabaseDefaults();

            // 计算矩形的四个角点
            double minX = Math.Min(corner1.X, corner2.X);
            double maxX = Math.Max(corner1.X, corner2.X);
            double minY = Math.Min(corner1.Y, corner2.Y);
            double maxY = Math.Max(corner1.Y, corner2.Y);

            // 添加四个顶点
            polyline.AddVertexAt(0, new Point2d(minX, minY), 0, 0, 0);
            polyline.AddVertexAt(1, new Point2d(maxX, minY), 0, 0, 0);
            polyline.AddVertexAt(2, new Point2d(maxX, maxY), 0, 0, 0);
            polyline.AddVertexAt(3, new Point2d(minX, maxY), 0, 0, 0);

            polyline.Closed = true;
            return polyline;
        }

        /// <summary>
        /// 检查矩形是否有效
        /// </summary>
        private static bool IsValidRectangle(Polyline rectangle)
        {
            try
            {
                if (rectangle.NumberOfVertices != 4)
                    return false;

                double width = Math.Abs(rectangle.GetPoint2dAt(1).X - rectangle.GetPoint2dAt(0).X);
                double height = Math.Abs(rectangle.GetPoint2dAt(2).Y - rectangle.GetPoint2dAt(1).Y);

                return width >= MinimumSize && height >= MinimumSize;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 创建圆角矩形
        /// </summary>
        public static ObjectId CreateRoundedRectangle(this Document document, double cornerRadius, short colorIndex = 1)
        {
            var editor = document.Editor;
            var database = document.Database;

            try
            {
                // 获取第一个角点
                var firstCornerResult = editor.GetPoint("指定第一个角点:");
                if (firstCornerResult.Status != PromptStatus.OK)
                    return ObjectId.Null;

                var firstCorner = firstCornerResult.Value;

                //// 获取另一个角点
                //var oppositeCornerResult = editor.GetPoint("\n指定另一个角点:", firstCorner);
                //if (oppositeCornerResult.Status != PromptStatus.OK)
                //    return ObjectId.Null;

                //var oppositeCorner = oppositeCornerResult.Value;

                // 获取另一个角点
                var oppositeOptions = new PromptPointOptions("\n指定另一个角点:")
                {
                    UseBasePoint = true,
                    BasePoint = firstCorner
                };

                var oppositeCornerResult = editor.GetPoint(oppositeOptions);
                if (oppositeCornerResult.Status != PromptStatus.OK)
                    return ObjectId.Null;

                var oppositeCorner = oppositeCornerResult.Value;

                // 创建圆角矩形
                var roundedRect = CreateRoundedRectangleFromCorners(firstCorner, oppositeCorner, cornerRadius);
                if (roundedRect == null)
                {
                    editor.WriteMessage("\n创建失败: 圆角半径太大");
                    return ObjectId.Null;
                }

                roundedRect.ColorIndex = colorIndex;

                return database.AddEntityToModelSpace(roundedRect);
            }
            catch (Exception ex)
            {
                editor.WriteMessage($"\n创建圆角矩形时发生错误: {ex.Message}");
                return ObjectId.Null;
            }
        }

        /// <summary>
        /// 创建圆角矩形
        /// </summary>
        private static Polyline CreateRoundedRectangleFromCorners(Point3d corner1, Point3d corner2, double cornerRadius)
        {
            double minX = Math.Min(corner1.X, corner2.X);
            double maxX = Math.Max(corner1.X, corner2.X);
            double minY = Math.Min(corner1.Y, corner2.Y);
            double maxY = Math.Max(corner1.Y, corner2.Y);

            double width = maxX - minX;
            double height = maxY - minY;

            // 检查圆角半径是否有效
            double maxRadius = Math.Min(width, height) / 2;
            if (cornerRadius > maxRadius)
                cornerRadius = maxRadius;

            var polyline = new Polyline();
            polyline.SetDatabaseDefaults();

            // 添加圆角矩形的顶点（简化版，实际需要更复杂的计算）
            // 这里使用简化实现，实际应用中可能需要使用圆弧段

            // 暂时使用直角矩形
            polyline.AddVertexAt(0, new Point2d(minX, minY), 0, 0, 0);
            polyline.AddVertexAt(1, new Point2d(maxX, minY), 0, 0, 0);
            polyline.AddVertexAt(2, new Point2d(maxX, maxY), 0, 0, 0);
            polyline.AddVertexAt(3, new Point2d(minX, maxY), 0, 0, 0);

            polyline.Closed = true;
            return polyline;
        }

        /// <summary>
        /// 批量创建多个矩形
        /// </summary>
        public static List<ObjectId> CreateMultipleRectangles(this Document document, short colorIndex = 1, int maxCount = 5)
        {
            var editor = document.Editor;
            var database = document.Database;
            var rectangleIds = new List<ObjectId>();

            try
            {
                editor.WriteMessage($"\n开始创建矩形，最多创建 {maxCount} 个。按ESC取消，按空格结束。");

                for (int i = 0; i < maxCount; i++)
                {
                    editor.WriteMessage($"\n创建第 {i + 1} 个矩形:");

                    var rectangleId = document.CreateRectangle(colorIndex);
                    if (rectangleId.IsNull)
                        break;

                    rectangleIds.Add(rectangleId);

                    // 询问是否继续
                    if (i < maxCount - 1)
                    {
                        var keywordOptions = new PromptKeywordOptions("\n继续创建下一个矩形？[是(Y)/否(N)]:")
                        {
                            AllowNone = true,
                            AppendKeywordsToMessage = true
                        };
                        keywordOptions.Keywords.Add("Y");
                        keywordOptions.Keywords.Add("N");
                        keywordOptions.Keywords.Default = "Y";

                        var result = editor.GetKeywords(keywordOptions);
                        if (result.Status != PromptStatus.OK || result.StringResult == "N")
                            break;
                    }
                }

                editor.WriteMessage($"\n成功创建 {rectangleIds.Count} 个矩形");
                return rectangleIds;
            }
            catch (Exception ex)
            {
                editor.WriteMessage($"\n创建矩形时发生错误: {ex.Message}");
                // 清理已创建的矩形
                foreach (var id in rectangleIds)
                {
                    try { id.EraseEntity(); } catch { }
                }
                return new List<ObjectId>();
            }
        }
    }
}